#include<tools/inthashmap.h>



void int_hash_map_free(Int_Hash_Map* ihm)
{
    if(ihm==NULL){return;}
    for(int i=0;i<ihm->container_size;i++)
    {
        //free_node_value(ihm->values[i]);
        int_rb_tree_free(ihm->values[i]);
    }
    LB_FREE(ihm->values);
    LB_FREE(ihm);
}
static int int_hash_map_insert(Int_Hash_Map*map,int key,void* data)
{
    int i=key%map->container_size;
    if(map->values[i]==NULL)
    {
        map->values[i]=(Int_RB_Tree*)LB_MALLOC(sizeof(Int_RB_Tree));
        int_rb_tree_init(map->values[i]);
    }
    if(map->values[i]->insert(map->values[i],key,data))
    {
        map->size++;
        return 1;
    }
    else
    {
        return 0;
    }

}
static void* int_hash_map_find(Int_Hash_Map* map, int key) {
    int i = key % map->container_size;
    if (map->values[i] == NULL) {
        return NULL;
    }
    return map->values[i]->find(map->values[i], key);
}

static int int_hash_map_erase(Int_Hash_Map* map, int key) {
    int i = key % map->container_size;
    if (map->values[i] == NULL) {
        return 0; // 如果该槽为空，表示没有这个键
    }
    if(map->values[i]->erase(map->values[i], key))
    {
        map->size--;
        return 1;
    }
    else
    {
        return 0;
    }
}


static void int_hash_map_next(Int_Hash_Map_Trav* trav) {
    if (trav->current_index >= trav->ihm->container_size) 
    {
        trav->it=NULL;
        return;}

    trav->current_trav.next(&trav->current_trav);
    if (trav->current_trav.it != NULL) {
        trav->first = trav->current_trav.it->key;
        trav->second = trav->current_trav.it->data;
        trav->it=trav->current_trav.it;
        return;
    }

    for (trav->current_index++; trav->current_index < trav->ihm->container_size; trav->current_index++) {
        if (trav->ihm->values[trav->current_index] != NULL && trav->ihm->values[trav->current_index]->size > 0) {
            trav->current_trav = trav->ihm->values[trav->current_index]->begin(trav->ihm->values[trav->current_index]);
            trav->first = trav->current_trav.it->key;
            trav->second = trav->current_trav.it->data;
            trav->it=trav->current_trav.it;
            return;
        }
    }

    trav->first = -1;
    trav->second = NULL;
    trav->it=NULL;
}

static void int_hash_map_prev(Int_Hash_Map_Trav* trav) {
    if (trav->current_index < 0) 
    {
        trav->it=NULL;
        return;
    }

    trav->current_trav.prev(&trav->current_trav);
    if (trav->current_trav.it != NULL) {
        trav->first = trav->current_trav.it->key;
        trav->second = trav->current_trav.it->data;
        trav->it=trav->current_trav.it;
        return;
    }

    for (trav->current_index--; trav->current_index >= 0; trav->current_index--) {
        if (trav->ihm->values[trav->current_index] != NULL && trav->ihm->values[trav->current_index]->size > 0) {
            trav->current_trav = trav->ihm->values[trav->current_index]->rbegin(trav->ihm->values[trav->current_index]);
            trav->first = trav->current_trav.it->key;
            trav->second = trav->current_trav.it->data;
            trav->it=trav->current_trav.it;
            return;
        }
    }

    trav->first = -1;
    trav->second = NULL;
    trav->it=NULL;
}

static void int_hash_map_trav_init(Int_Hash_Map_Trav* trav, Int_Hash_Map* ihm) {
    trav->ihm = ihm;
    trav->current_index = -1;
    trav->next = int_hash_map_next;
    trav->prev = int_hash_map_prev;
    int_rb_tree_trav_init(&(trav->current_trav));
    trav->first = -1;
    trav->second = NULL;
    trav->it=NULL;
    trav->prop = NULL;
    int_hash_map_next(trav);
}

void int_hash_map_resize(Int_Hash_Map* ihm, int size)
{
    for(int i=0;i<ihm->container_size;i++)
    {
        //free_node_value(ihm->values[i]);
        int_rb_tree_free(ihm->values[i]);
    }
    LB_FREE(ihm->values);

    ihm->container_size = size;
    ihm->size=0;
    if(size<=0)
    {
        ihm->values = (Int_RB_Tree**)LB_MALLOC(sizeof(Int_RB_Tree*) * size);
        memset(ihm->values, 0, sizeof(Int_RB_Tree*) * size);
    }
    
}
static Int_Hash_Map_Trav int_hash_map_begin(Int_Hash_Map* ihm) {
    Int_Hash_Map_Trav trav;
    int_hash_map_trav_init(&trav, ihm);

    return trav;
}

static Int_Hash_Map_Trav int_hash_map_rbegin(Int_Hash_Map* ihm) {
    Int_Hash_Map_Trav trav;
    trav.ihm = ihm;
    trav.current_index = ihm->container_size;
    trav.prev = int_hash_map_prev;
    trav.next = int_hash_map_next;
    int_rb_tree_trav_init(&(trav.current_trav));
    trav.first = -1;
    trav.second = NULL;
    trav.prop = NULL;
    int_hash_map_prev(&trav);
    return trav;
}


void int_hash_map_init(Int_Hash_Map* ihm, int size) {
    ihm->container_size = size;
    ihm->size=0;
    ihm->values = (Int_RB_Tree**)LB_MALLOC(sizeof(Int_RB_Tree*) * size);
    memset(ihm->values, 0, sizeof(Int_RB_Tree*) * size);

    ihm->find = int_hash_map_find;
    ihm->insert = int_hash_map_insert;
    ihm->erase = int_hash_map_erase;
    ihm->begin = int_hash_map_begin;
    ihm->rbegin = int_hash_map_rbegin;
}